#include "pr/FeatureSpace.h"
#include "pr/Pattern.h"
#include <cmath>

namespace pr {

FeatureSpace::FeatureSpace()
  : numFeatures_(0)
{
}

FeatureSpace::FeatureSpace(std::size_t numFeatures, const Pattern& eigenvalues, const std::vector<Pattern>& eigenvectors)
  : numFeatures_(numFeatures), eigenvalues_(eigenvalues), eigenvectors_(eigenvectors)
{
}

//util::Real FeatureSpace::transformPattern(Pattern& pattern) const
//{
//  ////// TODO
//  // Normalizzazione e standardizzazione vanno fatti sul PatternSet prima della proiezione nello spazio delle feature
////  pattern.normalize2();
//  // crea il pattern differenza dal valore medio del training set
////  pattern -= trmeanp;
//  // Registro il modulo del vettore differenza nello spazio completo
//  util::Real norm2orig = pattern.norm2();
//  // proietta il vettore sulle MEF
//  pattern.project(eigenvectors_);
//  util::Real norm2fs = pattern.norm2();
//  util::Real distanceFromFeatureSpace = sqrt(norm2orig*norm2orig - norm2fs*norm2fs);
//  // Calcolo Distance From Feature Space
//  pattern.normalize2();
//  return distanceFromFeatureSpace;
//}

Pattern FeatureSpace::transformPattern(const Pattern& pattern, util::Real& distanceFromFeatureSpace) const
{
  // Registro il modulo del vettore differenza nello spazio completo
  util::Real norm2orig = pattern.norm2();
  // proietta il vettore sulle MEF
  Pattern transformed = pattern.projection(eigenvectors_);
  // Calcolo Distance From Feature Space
  util::Real norm2fs = transformed.norm2();
  distanceFromFeatureSpace = sqrt(norm2orig*norm2orig - norm2fs*norm2fs);
  transformed.normalize2();
  return transformed;
}


////-------------------------------
//fspace::fspace(char *filename, util::Real& p1, int& p2, int ident) : id(ident), eigv(0,pvector(0)), trmeanp(0),
//                                                               eigval(0)
//{
//  std::ifstream conf;
//  conf.open(filename, std::ios::in | std::ios::binary);
//  unsigned int  i, j;
//
//  conf.read((char *)&id,sizeof(id));
//  conf.read((char *)&nfeature,sizeof(nfeature));
//  conf.read((char *)&nfo,sizeof(nfo));
//  conf.read((char *)&nc,sizeof(nc));
//  conf.read((char *)&nptr,sizeof(nptr));
//  conf.read((char *)&p1,sizeof(p1));
//  conf.read((char *)&p2,sizeof(p2));
//
//  trmeanp.resize(nfo);
//  eigval.resize(nfeature);
//  eigv.resize(nfeature,pvector(nfo));
//
//  for (i=0; i<nfo; i++)                           // mean pattern
//    conf.read((char *)&trmeanp[i],sizeof(util::Real));
//  for (i=0; i<nfeature; i++)                      // eigenvalues
//    conf.read((char *)&eigval[i],sizeof(util::Real));
//  for (i=0; i<nfeature; i++)                      // eigenvectors
//    for (j=0; j<nfo; j++)
//      conf.read((char *)&eigv[i][j],sizeof(util::Real));
//  conf.close();
//}
////----------------------------
//void fspace::savestate(char *filename, util::Real p1, int p2)
//{
//  std::ofstream conf(filename, std::ios::out | std::ios::binary);
//  unsigned int  i, j;
//  conf.write((char *)&id,sizeof(id));
//  conf.write((char *)&nfeature,sizeof(nfeature));
//  conf.write((char *)&nfo,sizeof(nfo));
//  conf.write((char *)&nc,sizeof(nc));
//  conf.write((char *)&nptr,sizeof(nptr));
//  conf.write((char *)&p1,sizeof(p1));
//  conf.write((char *)&p2,sizeof(p2));
//
//  for (i=0; i<nfo; i++)
//    conf.write((char *)&trmeanp[i],sizeof(util::Real)); // mean pattern
//  for (i=0; i<nfeature; i++)                      // eigenvalues
//    conf.write((char *)&eigval[i],sizeof(util::Real));
//  for (i=0; i<nfeature; i++)                      // eigenvectors
//    for (j=0; j<nfo; j++)
//      conf.write((char *)&eigv[i][j],sizeof(util::Real));
//  conf.close();
//}


/////////
// QUESTA 3 FUNZIONI SEGUENTI DEVONO ESSERE DIVISE IN
// 1) PREPROCESSING PATTERN SET (normalize e makedifftset)
// 2) EFFETTIVA PROJEZIONE NELLO SPAZIO DELLE FEATURE (project e normalize)
/////////

//void fspace::transformtrainingset(tset& trset)
//{
//  trset.normalize();
//  trset.makedifftset(trmeanp);
//  trset.project(eigv);
//  trset.normalize();
//}
////----------------------------
///*
//   1) sottrarre il valor medio da ogni vettore
//   2) proiettare i vettori lungo gli autovettori pi� significativi
//   3) effettuare la classificazione nearest neighbor sul nuovo test set
//*/
//void fspace::transformtestset(tset& testset, std::vector<util::Real>& dffs)
//{
//  unsigned int  i;
//
//  testset.normalize();
//  // crea il test set dei pattern differenza dal valore medio del training set
//  testset.makedifftset(trmeanp);
//  // Registro il modulo dei vettori differenza nello spazio completo
//  for (i=0; i<testset.length(); i++)
//    dffs[i] = testset[i].norm2();
//  // proietta i vettori sulle MEF
//  testset.project(eigv);
//  // Calcolo DFFS
//  for (i=0; i<testset.length(); i++)
//    dffs[i] = sqrt(dffs[i]*dffs[i]-testset[i].norm2()*testset[i].norm2());
//  testset.normalize();
//}
////-------------------------------
//void fspace::transformtestpattern(pvector& pv, util::Real& dffs)
//{
//  pv.normalize2();
//  // crea il pattern differenza dal valore medio del training set
//  pv.sub(trmeanp);
//  // Registro il modulo del vettore differenza nello spazio completo
//  dffs = pv.norm2();
//  // proietta il vettore sulle MEF
//  pv.project(eigv);
//  // Calcolo DFFS
//  dffs = sqrt(dffs*dffs-pv.norm2()*pv.norm2());
//  pv.normalize2();
//}

} // namespace pr
